﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections.Specialized;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;



/// <summary>
/// Takes JSON requests and passes them to the PowerSchool Server
/// </summary>
public class PSJSONrequests
{
    private string AccessToken = "";

    /// <summary>
    /// Generates a request to PowerSchool for the JSON data represented by the requestURL path
    /// </summary>
    /// <param name="requestURL"></param>
    /// <returns></returns>
	public JObject retrieveURL(string requestURL)
    {
        // Testing JSON CODE
        //JArray MyArray = new JArray();
        //foreach (KeyValuePair<string, string> item in QueryParameters)
        //{
        //    MyArray.Add(new JObject(new JProperty(item.Key,item.Value)));
        //}
        //return MyArray;

        String URL;
        String jsonResponse = "";
        NameValueCollection reqparm = new NameValueCollection();
        JObject jsonParsed;
        JToken objFound = "";
        String BaseURL = System.Configuration.ConfigurationManager.AppSettings["PowerSchoolServerURL"];

        try
        {
            using (WebClient req = new WebClient())
            {
                if(AccessToken == "")
                {
                    if(!getAccessToken())
                    {
                        jsonParsed = new JObject();
                        jsonParsed.Add("Error", "Could not retrieve the access token.");
                    }
                }
                // After the initial request receives the Access_Token, that token will be used for any subsequent
                // requests.
                req.Headers.Add("Authorization", "Bearer " + AccessToken);
                // This header specifies that the response must be in JSON format
                req.Headers.Add("Accept", "application/json");
                // The URL is changed to the requested data
                URL = BaseURL + "/" + requestURL;
                jsonResponse = req.DownloadString(URL);
                jsonParsed = JObject.Parse(jsonResponse);
            }
        }
        catch (WebException ex)
        {
            jsonParsed = new JObject();
            jsonParsed.Add("Error",ex.Message);
        }
        return jsonParsed;
    }

    /// <summary>
    /// Generates a update to PowerSchool, pushing the JSON data contained in jsonUpload to the uploadURL path
    /// </summary>
    /// <param name="uploadURL"></param>
    /// <param name="jsonUpload"></param>
    /// <returns></returns>
    public JObject putURL(string uploadURL, JObject jsonUpload)
    {
        String URL;
        String jsonResponse = "";
        NameValueCollection reqparm = new NameValueCollection();
        String LoginInfo;
        JObject jsonParsed;
        JToken objFound = "";
        String BaseURL = System.Configuration.ConfigurationManager.AppSettings["PowerSchoolServerURL"];

        try
        {
            using (WebClient req = new WebClient())
            {
                if (AccessToken == "")
                {
                    if (!getAccessToken())
                    {
                        jsonParsed = new JObject();
                        jsonParsed.Add("Error", "Could not retrieve the access token.");
                    }
                }
                // After the initial request receives the Access_Token, that token will be used for any subsequent
                // requests.
                req.Headers.Add("Authorization", "Bearer " + AccessToken);
                // This header specifies that the response must be in JSON format
                req.Headers.Add("Accept", "application/json");
                // This header specifies that the request is in JSON format
                req.Headers.Add("Content-Type", "application/json");
                // The URL is changed to the requested data
                URL = BaseURL + "/" + uploadURL;
                jsonResponse = req.UploadString(URL,"POST",jsonUpload.ToString());
                jsonParsed = JObject.Parse(jsonResponse);
            }
        }
        catch (WebException ex)
        {
            jsonParsed = new JObject();
            jsonParsed.Add("Error", ex.Message);
        }
        return jsonParsed;
    }

    /// <summary>
    /// Retrieves the PowerSchool access token for the current set of requests.
    /// </summary>
    /// <returns></returns>
    private bool getAccessToken()
    {
        String URL;
        String jsonResponse = "";
        NameValueCollection reqparm = new NameValueCollection();
        String LoginInfo;
        String Access_Token = "";
        JObject jsonParsed;
        JToken objFound = "";
        String BaseURL = System.Configuration.ConfigurationManager.AppSettings["PowerSchoolServerURL"];

        try
        {
            using (WebClient req = new WebClient())
            {
                URL = BaseURL + "/oauth/access_token";
                // This first request uses the username and password specified in the web.config file.
                LoginInfo = System.Configuration.ConfigurationManager.AppSettings["PowerSchoolAPIUser"] + ":" + System.Configuration.ConfigurationManager.AppSettings["PowerSchoolAPIPassword"];
                // The username and password are converted to Base64, then added as an "Authorization" header.
                // The credentials functionality specified by the webclient class are not sufficient for the custom
                // authentication required by powerschool.
                req.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(LoginInfo)));
                // The first request is for a that the system considers "client credentials" that will be used for 
                // the rest of the API calls.
                reqparm.Add("grant_type", "client_credentials");

                // This command actually sends the request to the server and receives the response in JSON format.
                // The response is placed in the string named "results" and is then parsed by JSON.NET.
                jsonResponse = Encoding.ASCII.GetString(req.UploadValues(URL, "POST", reqparm));

                jsonParsed = JObject.Parse(jsonResponse);

                // Trygetvalue returns true if the key was found, false if not.
                // This requires less exception handling than trying to directly access a
                // value that may not be there.
                if (jsonParsed.TryGetValue("access_token", out objFound))
                {
                    // The only value that is important in this first request is the access_token.
                    // This token will be used for the rest of the queries via the API and should always
                    // be requested at the beginning of the transaction.
                    AccessToken = objFound.ToString();
                    //Debugger.Text = objFound.ToString();
                }
                else
                {
                    return false;
                }
                req.Headers.Clear();
            }
        }
        catch (WebException ex)
        {
            // Passes any exception down the line so it can be handled.
            throw;
        }
        return true;
    }

}